package cn.gary.oaserver.config.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;
import javax.servlet.Filter;

/**
 * @Author: 邓必宏
 * @title:
 * @Demo:
 * @DateTime: 2024/3/15
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Resource
    private CustomFilter customFilter;
    @Resource
    private CustomUrlDecisionManager customUrlDecisionManager;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // 对访问权限进行控制
        http.authorizeRequests ( )
                .antMatchers ( "/login","/logout" ).permitAll ( )
                .anyRequest ( ).authenticated ( )
                .withObjectPostProcessor ( new ObjectPostProcessor<FilterSecurityInterceptor> ( ) {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        // 设置安全元数据源，这通常是定义哪些URL路径需要哪些权限的地方
                        // 在这里，你使用了一个自定义的Filter（可能是你提到的customFilter）来提供这些信息
                        o.setSecurityMetadataSource ( customFilter );
                        // 设置访问决策管理器，它负责决定用户是否有权访问特定的URL路径
                        // 你需要提供一个AccessDecisionManager的实例，这个实例会基于安全元数据源和其他配置来决定是否允许访问
                        o.setAccessDecisionManager ( customUrlDecisionManager );
                        return o;
                    }
                } );

        // 使用JWT，不需要csrf，调用disable()方法，关闭csrf防火墙
        http.csrf ( ).disable ( )
                .sessionManagement ( )
                .sessionCreationPolicy ( SessionCreationPolicy.STATELESS );

        //禁用头部缓存
        http.headers ( ).cacheControl ( );


        http.exceptionHandling ()
                .authenticationEntryPoint ( authenticationEntryPoint () )
                .accessDeniedHandler (accessDeniedHandler ()  );


        //添加拦截器
        http.addFilterBefore ( jwtFilter (), UsernamePasswordAuthenticationFilter.class );
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(
                "/login",
                "/logout",
                "/css/**",
                "/js/**",
                "/index.html",
                "favicon.ico",
                "/doc.html",
                "/webjars/**",
                "/swagger-resources/**",
                "/v2/api-docs/**"
        );

    }

    @Bean
    public AuthenticationEntryPoint authenticationEntryPoint(){
       return   new MyAuthenticationEntryPoint();
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler(){
        return new MyAccessDeniedHandler ();
    }

    @Bean
    public Filter jwtFilter(){
       return new JwtFilter();
    }
}
